package com.snail.common.mq.aspect;

import cn.hutool.json.JSONUtil;
import com.snail.common.core.utils.StringUtils;
import com.snail.common.mq.annotation.SnailMQLog;
import com.snail.common.mq.constants.MqConstants;
import com.snail.common.mq.core.dto.MqDto;
import com.snail.common.mq.exception.MqException;
import com.snail.common.mq.service.ISnailMqConsumerService;
import com.snail.common.mq.service.ISnailMqProducerService;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

/**
 * MQ日志记录处理
 *
 * @author snail
 */
@Aspect
@Component
public class MqLogAspect {
    private static final Logger log = LoggerFactory.getLogger(MqLogAspect.class);

    @Autowired
    private ISnailMqProducerService snailMqProducerService;
    @Autowired
    private ISnailMqConsumerService snailMqConsumerService;

    /**
     * 处理请求前执行
     */
    @Before(value = "@annotation(mqLog)")
    public void boBefore(JoinPoint joinPoint, SnailMQLog mqLog) {
        MqDto mqDto = JSONUtil.toBean(JSONUtil.parseObj(joinPoint.getArgs()[0]), MqDto.class);
        try {
            mqDto.setMqType(mqLog.mq());
            //消息生产
            if (MqConstants.PRODUCER.equals(mqLog.type())) {
                //判断消息是否重复发送
                if (snailMqProducerService.selectMqProducerCount(mqDto) > 0) {
                    throw new MqException(StringUtils.format("消息已经存在,请勿重复推送!", mqDto.getPriKey()));
                }
                snailMqProducerService.insertProducerInfo(mqDto, true, "");
            } else {
                snailMqConsumerService.insertConsumerInfo(mqDto, false, "消息消费中......");
            }
        } catch (Exception e) {
            log.error(StringUtils.format("MQ消息boBefore异常:消息{},{},{}",mqDto.getTopic(),mqDto.getPriKey(),e.getMessage()));
        }
    }

    /**
     * 处理完请求后执行
     *
     * @param joinPoint 切点
     */
    @AfterReturning(pointcut = "@annotation(mqLog)", returning = "jsonResult")
    public void doAfterReturning(JoinPoint joinPoint, SnailMQLog mqLog, Object jsonResult) {
        MqDto mqDto = JSONUtil.toBean(JSONUtil.parseObj(joinPoint.getArgs()[0]), MqDto.class);
        try {
            mqDto.setMqType(mqLog.mq());
            //消息消费
            if (MqConstants.CONSUMER.equals(mqLog.type())) {
                snailMqConsumerService.insertConsumerInfo(mqDto, true, "");
                //生产消息异常删除生产记录
                snailMqProducerService.deleteMqProducer(mqDto);
            }
        } catch (Exception e) {
            log.error(StringUtils.format("MQ消息doAfterReturning异常:消息{},{},{}",mqDto.getTopic(),mqDto.getPriKey(),e.getMessage()));
        }
    }

    /**
     * 拦截异常操作
     *
     * @param joinPoint 切点
     * @param e         异常
     */
    @AfterThrowing(value = "@annotation(mqLog)", throwing = "e")
    public void doAfterThrowing(JoinPoint joinPoint, SnailMQLog mqLog, Exception e) {
        MqDto mqDto = JSONUtil.toBean(JSONUtil.parseObj(joinPoint.getArgs()[0]), MqDto.class);
        try {
            mqDto.setMqType(mqLog.mq());
            //消息消费
            if (MqConstants.CONSUMER.equals(mqLog.type())) {
                snailMqConsumerService.insertConsumerInfo(mqDto, false, e.getMessage());
            }else{
                //生产消息异常删除生产记录
                snailMqProducerService.deleteMqProducer(mqDto);
            }
        } catch (Exception ex) {
            log.error(StringUtils.format("MQ消息doAfterReturning异常:消息{},{},{}",mqDto.getTopic(),mqDto.getPriKey(),e.getMessage()));
        }
    }
}
